#include "stdafx.h"
#include <cstdlib> 
#include <time.h>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

//Global Constants
string SIGNATURE = "*dVault!";
int ENCRYPTED = 1;
int DECRYPTED = 2;
int ASCII = 255;
string EXIT = "exit";
//Errors
string INVALID_FILE = "Invalid File";
string INVALID_NAME = "Invalid File Name";
string INVALID_KEY = "Invalid Key";
string getInput(string instr){
	cout << instr;
	string io;
	getline(cin, io);
	return io;
}

string loadFile(string file_name){
	ifstream ifs(file_name, ifstream::in);;
	string data = "";
	char c;
	while (ifs.good()) {
		c = ifs.get();
		data += c;
	}
	ifs.close();
	return data;
}

int saveFile(string filename, string data){
	string conf = string();
	while (_stricmp(conf.c_str(), "Y") != 0 && _stricmp(conf.c_str(), "N") != 0){
		conf = getInput("\nSave File (Y/N)?:");
	}
	if (conf == "Y" | conf == "y") {
		ofstream outfile(filename, ofstream::binary);
		outfile.write(data.c_str(), data.size());
		outfile.close();
	}
	return 0;
}
int isEncrypted(string file_data){
	string::size_type enc = file_data.find(SIGNATURE);
	return (enc == string::npos) ? DECRYPTED : ENCRYPTED;
}

string header(string filename){
	string::size_type pos = filename.rfind("/");
	string head = (pos != string::npos) ? filename.substr(pos + 1, string::npos) : filename;
	return "--header[file:" + head + ", ascii:" + to_string(ASCII) + "]";
}
string encrypt(string name, string text){
	string en_file = string();
	//Get Encryption Key
	string key = getInput("Encryption Key:");
	while (key.size() < 8){
		cout << INVALID_KEY;
		key = getInput("Encryption Key:");
	}

	// Get Header location
	srand((unsigned)time(0));
	string head = header(name);
	int hd_loc = rand()%text.size();
	
	// Encrypt
	int i=0, j=0, h=0;
	while (i < text.size()-1){
		char e_char = (i >= hd_loc && h < head.size()) ? head[h++] : text[i++];
		int val = (e_char + key[j++])%ASCII;
		en_file += val;
		j = j%key.size();
	}

	return en_file;
}

string decrypt(string text){
	string d_file = string();
	// geting the key
	string key = getInput("This file is encrypted please insert a key to decrypt the file\nKey:");
	// removing signature
	string uText = text.substr(text.find('!') + 1, string::npos);
	int i = 0,j = 0;
	while (i < uText.size() - 1){
		int dchar = uText[i++]-key[j++];
		d_file += dchar;
		j = j%key.size();
	}
	return d_file;
}

int runVault(){
	/*Get file*/
	string fileName = getInput("File:");
	string f_data = loadFile(fileName);
	string newFile;
	if (f_data.size() <= 0){
		cout << INVALID_FILE;
		return 0;
	}
	if (isEncrypted(f_data) == 1){
		newFile = decrypt(f_data);
		//Checking key
		int pos = newFile.find("--header[file:");
		if (pos ==string::npos){
			cout << INVALID_KEY;
			return 0;
		}
		// removing header
		string a = newFile.substr(0,pos);
		int pos2 = newFile.substr(pos,string::npos).find("]")+1;
		string head = newFile.substr(pos,pos2);
		string b = newFile.substr(pos+pos2,string::npos);
		newFile = a+b;
		cout << newFile;
		// get filename
		pos = head.find(":")+1;
		pos2 = head.find(",");
		string fname = head.substr(pos,pos2-pos);
		saveFile(fname,newFile);
	}
	else{
		newFile = encrypt(fileName,f_data);
		cout << newFile;
		string conf = string();
		saveFile("encfile", SIGNATURE + newFile);
	}
	return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
	string run = string();
	while (_stricmp(run.c_str(),EXIT.c_str())!= 0){
		runVault();
		run = getInput("\n>>");
	}
	return 0;
}

